import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { beginCell, toNano, Cell } from '@ton/core';
import styled from 'styled-components'
import Message from '../../component/Message'
import { DetectorTypeInfo, PurchaseConfirm, TonSendTransaction } from '../../service/interface'
import Empty from '../../component/Empty'
import { check, purchase, upgradeSpeed } from '../../service'
import Item from './Item'
import Loading from '../../component/Loading'
import Success from './Success'
import { TonConnectError, useTonAddress, useTonConnectUI } from '@tonconnect/ui-react'
import { useTranslation } from 'react-i18next'
import { fetchOrder, removeOrder, saveOrder } from '../../utils/ton';
import Footer from './Footer';

const VALID_UNTIL = 1000 * 60 * 60; // 5 minutes

const Container = styled.div`
    display: flex;
    flex-direction: column;
    flex: 1;
    padding: .625rem .9375rem;
    box-sizing: border-box;
    >:not(:last-child) {
        margin-bottom: .75rem;
    }
`

const List: React.FC = () => {
    const [tonConnectUI] = useTonConnectUI();
    const userFriendlyAddress = useTonAddress();
    const { t } = useTranslation()
    const [list, setList] = useState<Array<DetectorTypeInfo>>([])
    const [loading, setLoading] = useState(false)
    const [show, setShow] = useState(false)
    const isEmpty = useMemo(() => !list?.length, [list])

    const timer = useRef<NodeJS.Timeout>()

    const fetchData = useCallback(async () => {
        timer?.current && clearTimeout(timer.current)
        setLoading(true)
        const result = await upgradeSpeed();
        setLoading(false)
        if (!result.success) {
            Message.error(result.message)
            return
        }

        const data = result.data as Array<DetectorTypeInfo> || []
        setList(data)

        const check = data.find(e => e.purchaseConfirm === PurchaseConfirm.Pendding)
        if (!check) {
            return
        }

        // check pendding
        timer.current = setTimeout(() => {
            fetchData()
        }, 10 * 1000);

        return () => {
            clearTimeout(timer.current)
            timer.current = undefined
        }
    }, [])

    useEffect(() => {
        fetchData()
        try {
            const info = fetchOrder()
            if (info) {
                purchase(info as TonSendTransaction).then(() => {
                    removeOrder()
                    fetchData()
                })
            }
        } catch (error) {
            // temp
        }


    }, [fetchData])

    const handlePurchase = async (item: DetectorTypeInfo) => {
        setLoading(true)
        const result = await check({ amount: item.purchaseAmount, detectorType: item.detectorType })
        if (!result.success) {
            Message.error(result.message)
            setLoading(false)
            return
        }

        if (!result.data?.address) {
            Message.error(t('ton.transaction.error'))
            setLoading(false)
            return
        }

        try {
            const body = beginCell().storeInt(0, 32).storeStringTail(result.data.comment).endCell().toBoc().toString('base64')
            const order = {
                address: result.data.address,
                amount: toNano(item.purchaseAmount).toString(),
                payload: body
            }
            const info = await tonConnectUI.sendTransaction({
                validUntil: Math.round((Date.now() + VALID_UNTIL) / 1000),
                messages: [
                    order
                ]
            })

            if (!info?.boc) {
                setLoading(false)
                return
            }

            const cell = Cell.fromBase64(info.boc)
            const hash = cell.hash().toString('hex')

            const params = { amount: item.purchaseAmount, detectorType: item.detectorType, serialNo: result.data.serialNo, hash, address: userFriendlyAddress };
            const res = await purchase(params)
            if (!res.success) {
                try {
                    saveOrder(JSON.stringify(params))
                } catch (error) {
                    // temp
                }
                setLoading(false)
                Message.error(res.message)
                return
            }

            setTimeout(() => {
                setLoading(false)
                setShow(true)
            }, 200);

        } catch (error: unknown) {
            setLoading(false)
            console.log(error)
            if (error instanceof TonConnectError) {
                // user cancel
                return
            }
            Message.error((error as Error).message || t('ton.transaction.error'))
        }
    }

    const handleClose = () => {
        setShow(false)
        fetchData()
    }

    return <Container>
        {isEmpty ? <Empty /> : list.map(item => <Item
            key={item.title}
            data={item}
            onClick={() => handlePurchase(item)}
        />)}
        {!isEmpty && <Footer />}
        <Loading show={loading} />
        <Success
            show={show}
            onClose={handleClose}
        />
    </Container>
}

export default List